#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>


template<class T>
class vector
{
public:
	typedef T* iterator;
	typedef const T* const_iterator;
	vector(int& n) :_start(nullptr), _finish(nullptr), _capacity(nullptr)
	{
		;
	}

	vector(int n)
	{
		_start = new T[n];
		_finish = _start;
		_capacity = _start + n - 1;
	}

	vector(int n, const T& value = T())
	{
		resize(n, value);
	}

	vector(const vector<T>& v)
	{
		reserve(v.capacity());
		for (const auto e : v)
		{
			push_back(e);
		}
	}

	vector<T>& operator= (vector<T> v)
	{
		reserve(v.capacity());
		for (const auto e : v)
		{
			push_back(e);
		}
		return *this;
	}

	~vector()
	{
		delete[] _start;
		_start = _finish = _capacity = nullptr;
	}

	iterator begin()
	{
		return _start;
	}

	iterator end()
	{
		return _finish;
	}

	const_iterator cbegin()const
	{
		return _start;
	}

	const_iterator cend()const
	{
		return _finish();
	}

	T& operator[](size_t pos)
	{
		assert(pos < size() && pos >= 0);
		return this->_start + pos;
	}

	const T& operator[](size_t pos)const
	{
		assert(pos < size() && pos >= 0);
		return this->_start + pos;
	}

	size_t size()
	{
		return _finish - _start;
	}

	size_t Capacity()
	{
		return _capacity - _start;
	}

	void reserve(size_t n)
	{
		if (n > Capacity())
		{
			size_t len = _finish - _start;
			T* newcapacity = new T[n];
			memcpy(newcapacity, _start, sizeof(T) * n);
			delete[] _start;
			_start = newcapacity;
			_finish = _start + len;
			_capacity = _start + n;
		}
	}

	void resize(size_t n, const T& value = T())
	{
		assert(n > 0);
		if (n > Capacity())
		{
			reserve(n);
			strncpy(this->_finish, value, sizeof(T) * (n - size()));
		}
		else
		{
			this->_finish = this->_start + n;
		}
	}

	void swap(vector<T>& v)
	{
		std::swap(v._start, _start);
		std::swap(v._finish, _finish);
		std::swap(v._capacity, _capacity);
	}

	void push_back(const T& n)
	{
		if (this->_finish == this->_capacity)
		{
			size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;
			reserve(newcapacity);
		}
		*(this->_finish) = n;
		this->_finish++;
	}

	void push_back(const T& n)
	{
		Insert(_finish, n);
	}

	void pop_back()
	{
		assert(size() > 0);
		this->_finish--;
	}

	void pop_back()
	{
		erase(_finish);
	}

	T* Insert(T* pos,const T& n)
	{
		assert(pos <= _finish && pos >= _start);
		if (_finish == _capacity)
		{
			size_t len = pos - _finish;
			reserve(capacity() == 0 ? 4 : capacity() * 2);
			pos = _start + len;
		}
		memmove(pos + 1, pos, sizeof(T) * (this->_finish - pos - 1));
		*pos = n;
		return _finish++;
	}

	T* erase(T* pos)
	{
		assert(_start != _finish && pos >= _start && pos <= _finish);
		memmove(pos, pos + 1, sizeof(T) * (this->_finish - pos - 1));
		this->_finish--;
	}
private:
	T* _start;
	T* _finish;
	T* _capacity;
};